<?php
namespace common\models;

use yii\base\Exception;

/**
 * 所有用到的redis key
 * Class RedisKeys
 * @package common\models
 */
class CacheKeys
{
    # 验证码
    const CACHE_CODE_TYPE_LOGIN = 'LOGIN_CODE';
    const CACHE_CODE_TYPE_REGISTER_CODE = 'REGISTER_CODE';
    const CACHE_CODE_TYPE_FORGET_CODE = 'CACHE_CODE_TYPE_FORGET_CODE';
    const CACHE_CODE_TYPE_MODIFY_PASSWORD_PHONE = 'CACHE_CODE_TYPE_MODIFY_PASSWORD_PHONE';
    const CACHE_CODE_TYPE_RESET_PAY_PASS_CODE = 'CACHE_CODE_TYPE_PAY_PASS_CODE';
    const CACHE_CODE_TYPE_PLACE_PHONE = 'CACHE_CODE_TYPE_PLACE_PHONE';
    const CACHE_CODE_TYPE_MONEY_SWITCH_CODE = 'CACHE_CODE_TYPE_MONEY_SWITCH_CODE';


    const CACHE_GIVE_POP_PREFIX = 'GIVE_POP_HOME_';    #并发锁


    # IM
    const IM_APPLY_FRIEND = "IM_APPLY_FRIEND";  // 申请好友
    const IM_CREATE_GROUP = "IM_CREATE_GROUP";  // 创建群聊
    const IM_SEND_RED_PACKET = "IM_SEND_RED_PACKET";                       //发红包
    const IM_TRANSFER = "IM_TRANSFER";                       //转账
    const IM_RED_PACKET = "IM_RED_PACKET:";                                           //红包
    const IM_RED_PACKET_WAIT_LIST = "IM_RED_PACKET_WAIT_LIST:";                               //红包名额记录
    const IM_RED_PACKET_LOCK_LIST = "IM_RED_PACKET_LOCK_LIST:";                               //红包锁定记录
    const IM_SEND_BUSINESS_CARD = "IM_SEND_BUSINESS_CARD:";                               //发送名片
    const IM_SEND_GIFT = "IM_SEND_GIFT:";                               //赠送礼物

    public static function getGiveLock($id = 0) {
        $redis = \Yii::$app->redis;
        $key = static::CACHE_GIVE_POP_PREFIX . $id;
//        $res = $redis->lpop($key);
        $res = $redis->llen($key);
        return $res;
    }

    public static function setGiveLock($id = 0) {
        $redis = \Yii::$app->redis;
        $key = static::CACHE_GIVE_POP_PREFIX . $id;
        $redis->lpush($key, 1);
    }

    public static function removeGiveLock($id = 0) {
        $redis = \Yii::$app->redis;
        $key = static::CACHE_GIVE_POP_PREFIX . $id;
        $redis->remove($key);
    }
    /**
     * 根据数据库的查询条件生成Key  用来缓存数据
     * @param string $tableName
     * @param array  $where
     * @param array  $andWhere
     * @param array  $fields
     * @param string $order
     * @param string $offset
     * @param string $limit
     *
     * @return string
     */
    public static function cacheKey($tableName = '', $where = [], $andWhere = [], $fields = [], $order = '', $offset = '', $limit = '') {
        if (is_array($where)) {
            asort($where);
        }

        if (is_array($andWhere)) {
            asort($andWhere);
        }

        if (is_array($fields)) {
            asort($fields);
        }

        if (is_array($order)) {
            asort($order);
        }

        $data['where'] = $where;
        $data['andWhere'] = $andWhere;
        $data['fields'] = $fields;
        $data['order'] = $order;
        $data['offset'] = $offset;
        $data['limit'] = $limit;
        $data['tableName'] = $tableName;
        $dataStr = serialize($data);
        return  \Yii::$app->params['REDIS_TABLE_PREFIX'] . md5($dataStr);
    }

    /**
     * 获取缓存时间 -- 如果没有设置失效时间则设置上失效时间
     * @param string $key
     * @param int    $expire
     *
     * @return mixed
     */
    public static function getCacheWithExpire($key = '', $expire = 10) {
        $key = \Yii::$app->params['REDIS_TABLE_PREFIX'] . $key;
        $redis = \Yii::$app->get('redis');
        $ttl = $redis->ttl($key);     #-2 已经过期 -1未设置过期时间
        if ($ttl === -1) {
            $redis->expire($key, $expire);
        }
        $result = json_decode($redis->get($key), true);
        return $result;
    }

    /**
     * 设置缓存失效时间
     * @param string $key
     * @param string $data
     * @param int    $expire
     */
    public static function setCacheWithExpire($key = "", $data = '', $expire = 10) {
        $key = \Yii::$app->params['REDIS_TABLE_PREFIX'] . $key;
        $redis = \Yii::$app->get('redis');
        $redis->set($key, $data);
        $redis->expire($key, $expire);
    }

    /**
     * @param string $key
     * @param int    $expTime
     *
     * @return bool
     */
    public static function setLock($key = '', $expTime = 3)
    {
        $key = \Yii::$app->params['REDIS_TABLE_PREFIX'] . $key;
        $redis = \Yii::$app->redis;
        //初步加锁
        $setLock = $redis->setnx($key, 1);
        if($setLock == 1) {
            $redis->expire($key, $expTime);
            return true;
        }
        return false;
    }

    /**
     * @param $key
     */
    public static function delLock($key)
    {
        $key = \Yii::$app->params['REDIS_TABLE_PREFIX'] . $key;
        \Yii::$app->redis->del($key);
    }

    /**
     * 控制请求频率，防止并发重复请求
     * @param int $user
     * @param int $duration
     * @throws Exception
     * @throws \yii\base\InvalidConfigException
     */
    public static function checkFrequency($user = 0, $duration = 1, $msg = '操作过于频繁') {
        $key = "REQUEST_FREQUENCY_" . $user;
        if (empty($user)) {
            $ip = Functions::getRemoteIp();
            $key = "REQUEST_FREQUENCY_" . $ip;
        }

        $redis = \Yii::$app->get("redis");

        $lock = $redis->set($key, 1, 'EX', $duration, "NX");
        if ($lock !== true) {
            throw new Exception($msg);
        }
    }

    /**
     * 移除锁
     * @param int $user
     * @param int $duration
     * @throws Exception
     * @throws \yii\base\InvalidConfigException
     */
    public static function removeFrequency($user = 0) {
        $key = "REQUEST_FREQUENCY_" . $user;
        if (empty($user)) {
            $ip = Functions::getRemoteIp();
            $key = "REQUEST_FREQUENCY_" . $ip;
        }

        $redis = \Yii::$app->get("redis");

        $redis->del($key);
    }

}


